// 本地视频预览窗口
var localVideo =
    document.querySelector('video#localvideo ');

// 远端视频预览窗口
var remoteVideo =
    document.querySelector('video#remotevideo ');

// 连接信令服务器Button
var btnConn =
    document.querySelector('button#connserver ');

// 与信令服务器断开连接Button
var btnLeave =
    document.querySelector('button#leave ');

// 查看Offer 文本窗口
var offer =
    document.querySelector('textarea#offer ');

// 查看Answer 文本窗口
var answer =
    document.querySelector('textarea#answer ');

var pcConfig = {
    'iceServers ': [{
        //TURN 服务器地址
        'urls': 'turn:xxx.avdancedu.com :3478 ',
        //TURN 服务器用户名
        'username ': "xxx",
        //TURN 服务器密码
        'credential ': "xxx"
    }],
    // 默认使用relay 方式传输数据
    "iceTransportPolicy": "relay",
    "iceCandidatePoolSize": "0"
};

// 本地视频流
var localStream = null;
// 远端视频流
var remoteStream = null;

// PeerConnection
var pc = null;

// 房间号
var roomid;
var socket = null;

// offer 描述
var offerdesc = null;

// 状态机， 初始为init
var state = 'init';

/**
* 功能： 判断此浏览器是在PC 端， 还是移动端。
*
* 返回值： false ， 说明当前操作系统是移动端；
*                true ， 说明当前的操作系统是PC 端。
*/
function IsPC() {
    var userAgentInfo = navigator.userAgent;
    var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
    var flag = true;

    for (var v = 0; v < Agents.length; v++) {
        if (userAgentInfo.indexOf(Agents[v]) > 0) {
            flag = false;
            break;
        }
    }

    return flag;
}

/**
* 功能： 判断是Android 端还是iOS 端。
*
* 返回值： true ， 说明是Android 端；
* false ， 说明是iOS 端。
*/
function IsAndroid() {
    var u = navigator.userAgent, app = navigator.appVersion;
    var isAndroid = u.indexOf('Android ') > -1 || u.indexOf('Linux ') > -1;
    var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    if (isAndroid) {
        // 这个是Android 系统
        return true;
    }

    if (isIOS) {
        // 这个是iOS 系统
        return false;
    }
}

/**
* 功能： 从url 中获取指定的域值
*
* 返回值： 指定的域值或false
*/
function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split("&");
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split("=");
        if (pair[0] == variable) {
            return pair[1];
        }
    }
    return false;
}

/**
* 功能： 向对端发消息
*
* 返回值： 无
*/
function sendMessage(roomid, data) {
    console.log('send message to other end',
        roomid, data);
    if (!socket) {
        console.log('socket is null');
    }
    socket.emit('message ', roomid, data);
}

/**
* 功能： 与信令服务器建立socket.io 连接；
* 并根据信令更新状态机。
*
* 返回值： 无
*/
function conn() {

    // 连接信令服务器
    socket = io.connect();

    //'joined ' 消息处理函数
    socket.on('joined ', (roomid, id) => {
        console.log('receive joined message!',
            roomid, id);

        // 状态机变更为'joined '
        state = 'joined '

        /**
        * 如果是Mesh 方案， 第一个人不该在这里创建
        * peerConnection ， 而是要等到所有端都收到
        * 一个'otherjoin ' 消息时再创建
        */

        // 创建PeerConnection 并绑定音视频轨
        createPeerConnection();
        bindTracks();

        // 设置button 状态
        btnConn.disabled = true;
        btnLeave.disabled = false;
        console.log('receive joined message , state = ', state);
      });

    // otherjoin 消息处理函数
    socket.on('otherjoin ', (roomid) => {
        console.log('receive joined message:',
            roomid, state);

        // 如果是多人， 每加入一个人都要创建一个新的PeerConnection
        if (state === 'joined_unbind ') {
            createPeerConnection();
            bindTracks();
        }

        // 状态机变更为joined_conn
        state = 'joined_conn ';

        // 开始“ 呼叫” 对方
        call();

        console.log('receive other_join message ,  state = ', state);
      });

    //full 消息处理函数
    socket.on('full', (roomid, id) => {
        console.log('receive full message ',
            roomid, id);

        // 关闭socket.io 连接
        socket.disconnect();
        // 挂断“ 呼叫”
        hangup();
        // 关闭本地媒体
        closeLocalMedia();
        // 状态机变更为leaved
        state = 'leaved ';

        console.log('receive full message , state = ', state);
      alert('the room is full!');
    });

    // leaved 消息处理函数
    socket.on('leaved ', (roomid, id) => {
        console.log('receive leaved message ',
            roomid, id);

        // 状态机变更为leaved
        state = 'leaved '
        // 关闭socket.io 连接
        socket.disconnect();
        console.log('receive leaved message , state = ', state);

      // 改变button 状态
      btnConn.disabled = false;
        btnLeave.disabled = true;
    });

    //bye 消息处理函数
    socket.on('bye', (room, id) => {
        console.log('receive bye message ',
            roomid, id);

        /**
        * 当是Mesh 方案时， 应该带上当前房间的用户数,
        * 如果当前房间用户数不小于2, 则不用修改状态,
        * 并且关闭的应该是对应用户的PeerConnection 。
        * 在客户端应该维护一张PeerConnection 表， 它是
        * key:value 的格式， key=userid , value=peerconnection
        */

        // 状态机变更为joined_unbind
        state = 'joined_unbind ';

        // 挂断“ 呼叫”
        hangup();

        offer.value = '';
        answer.value = '';
        console.log('receive bye message , state=', state);
    });

    // socket.io 连接断开处理函数
    socket.on('disconnect ', (socket) => {
        console.log('receive disconnect message!',
            roomid);
        if (!(state === 'leaved ')) {
            // 挂断“ 呼叫”
            hangup();
            // 关闭本地媒体
            closeLocalMedia();
        }

        // 状态机变更为leaved
        state = 'leaved ';

    });

    // 收到对端消息处理函数
    socket.on('message ', (roomid, data) => {    console.log('receive message!',
